﻿using ShengYueWorkShop.BLL.DataModel;
using ShengYueWorkShop.BLL.PublicHelper;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ShengYueWorkShop.BLL.Tcp
{
    public class ClientHelper
    {
        #region 变量
        /// <summary>
        /// 服务器IP
        /// </summary>
        private string _ServerIp;
        /// <summary>
        /// 传入参数：服务器IP
        /// </summary>
        public string GetServerIp
        {
            get { return _ServerIp; }
            set
            {
                IPAddress fIp;
                if (IPAddress.TryParse(value, out fIp))
                {
                    _ServerIp = fIp.ToString();
                }
                else
                {
                    _ServerIp = "127.0.0.1";
                }
            }
        }

        /// <summary>
        /// 服务器端口
        /// </summary>
        private int _ServerPort;
        /// <summary>
        /// 传入参数：服务器端口
        /// </summary>
        public int GetServerPort
        {
            get { return _ServerPort; }
            set
            {
                if (value > 0)
                {
                    _ServerPort = value;
                }
                else
                {
                    _ServerPort = 0;
                }
            }
        }

        /// <summary>
        /// Token
        /// </summary>
        private string _Token;
        /// <summary>
        /// 传入参数：服务器Token
        /// </summary>
        public string GetToken
        {
            get { return _Token; }
            set
            {
                if (value.Length > 0)
                {
                    _Token = value;
                }
                else
                {
                    _Token = "";
                }
            }
        }

        private TcpReadStruct _TcpReadStruct;
        private string _ServerMsg;
        /// <summary>
        /// 服务器客户端对象
        /// </summary>
        private TcpClient _TcpClient;
        /// <summary>
        /// Token是否通过验证
        /// </summary>
        private bool _TokenPass = false;
        /// <summary>
        /// 数据流
        /// </summary>
        private NetworkStream _Stream;
        /// <summary>
        /// 消息流，常用于错误信息
        /// </summary>
        public string _Msg;
        #endregion
        #region 功能操作
        /// <summary>
        /// 启动客户端，并验证Token 
        /// </summary>
        /// <returns></returns>
        public bool SatrServer()
        {
            if (_ServerIp.Length == 0 || _ServerPort == 0 || _Token.Length == 0)
            {
                _Msg = "服务器参数不完整";
                return false;
            }
            else
            {
                bool flag = true;
                try
                {
                    //实例化TcpClient,并设置读写超时时间
                    _TcpClient = new TcpClient(_ServerIp, _ServerPort);
                    //获取数据流
                    _Stream = _TcpClient.GetStream();
                    //设置超时时间
                    _Stream.ReadTimeout = TcpOperationCommand.TimeOut;
                    _Stream.WriteTimeout = TcpOperationCommand.TimeOut;

                    //验证Token
                    flag = ValidateToken();
                }
                catch (Exception ex)
                {
                    _Msg = ex.ToString();
                    flag = false;
                }
                finally
                {
                    //如果没有通过验证则关闭连接
                    if (!_TokenPass)
                    {
                        _TcpClient?.Close();
                    }
                }
                return flag;
            }
        }
        /// <summary>
        /// 验证Token
        /// </summary>
        /// <returns></returns>
        private bool ValidateToken()
        {
            //判断服务出于连接状态
            if (_TcpClient != null && _TcpClient.Client.Connected)
            {
                _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.Token, _Token, true);
                if(_TcpReadStruct.ReadStatus && _TcpReadStruct.TcpOperationCommand== TcpOperationCommand.Token)
                {
                    _ServerMsg = Encoding.UTF8.GetString(_TcpReadStruct.Message);
                    if (Boolean.TryParse(_ServerMsg, out _TokenPass))
                    {
                        if (!_TokenPass)
                        {
                            _Msg = "Token验证失败";
                            _TcpClient?.Close();
                        }
                    }
                }
            }
            return _TokenPass;
        }
        /// <summary>
        /// 获取服务器当前目录下的所有文件及目录
        /// </summary>
        /// <returns></returns>
        public List<FileListStruct> GetAll()
        {
            List<FileListStruct> fFileList = new List<FileListStruct>();
            try
            {
                _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.GetList, "", true);
                if (_TcpReadStruct.ReadStatus && _TcpReadStruct.TcpOperationCommand == TcpOperationCommand.GetList)
                {
                    _ServerMsg = Encoding.UTF8.GetString(_TcpReadStruct.Message);
                    fFileList = JSONHelper.DeserializeObject<List<FileListStruct>>(_ServerMsg);
                }
            }
            catch (Exception ex)
            {
                _Msg = ex.ToString();
            }
            return fFileList;
        }
        /// <summary>
        /// 从当前目录进入下一级目录
        /// </summary>
        /// <param name="pDirectoryName"></param>
        /// <returns></returns>
        public bool EnterDirectory(string pDirectoryName)
        {
            bool flag = false;
            try
            {
                _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.EnterDir, pDirectoryName, true);
                //读取反馈的消息
                if (_TcpReadStruct.ReadStatus && _TcpReadStruct.TcpOperationCommand == TcpOperationCommand.EnterDir)
                {
                    _ServerMsg = Encoding.UTF8.GetString(_TcpReadStruct.Message);
                    Boolean.TryParse(_ServerMsg, out flag);
                }
            }
            catch (Exception ex)
            {
                _Msg = ex.ToString();
            }
            return flag;
        }
        /// <summary>
        /// 从当前目录返回到上级目录
        /// </summary>
        /// <returns></returns>
        public bool ComtOutDirectory()
        {
            bool flag = false;
            try
            {
                _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.ComeOutDir, "", true);
                //读取反馈的消息
                if (_TcpReadStruct.ReadStatus && _TcpReadStruct.TcpOperationCommand == TcpOperationCommand.ComeOutDir)
                {
                    _ServerMsg = Encoding.UTF8.GetString(_TcpReadStruct.Message);
                    Boolean.TryParse(_ServerMsg, out flag);
                }
            }
            catch (Exception ex)
            {
                _Msg = ex.ToString();
            }
            return flag;
        }
        /// <summary>
        /// 向服务端发送关闭的命令
        /// </summary>
        public void ClinetClosed()
        {
            try
            {
                if (_TcpClient.Client.Connected)
                {
                    _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.Closed, "", false);
                }
            }
            catch (Exception ex)
            {
                _Msg = ex.ToString();
            }
        }
        public Image GetPicZip(string pFileName)
        {
            Image fFile = null;
            try
            {
                _TcpReadStruct = WriteAndReadMsg(TcpOperationCommand.GetPicZip, pFileName, true);
                //读取反馈的消息
                if (_TcpReadStruct.ReadStatus && _TcpReadStruct.TcpOperationCommand == TcpOperationCommand.GetPicZip)
                {
                    fFile = PicHelper.BytesToImage(_TcpReadStruct.Message);
                    //fFile = PicHelper.BytesToImage(Encoding.Default.GetBytes(fMsg));
                }
            }
            catch (Exception ex)
            {
                _Msg = ex.ToString();
            }
            return fFile;
        }
        #endregion
        #region 消息发送及处理
        private TcpReadStruct WriteAndReadMsg(string pTcpCommand, string pMsg, bool pIsReutrn)
        {
            TcpReadStruct pTcpStruct = new TcpReadStruct()
            {
                ReadStatus = false,
            };
            ServerSend(pTcpCommand, pMsg);
            if (pIsReutrn)
            {
                pTcpStruct = ServerRead();
                if (pTcpStruct.ReadStatus)
                {
                    if (pTcpCommand != pTcpStruct.TcpOperationCommand)
                    {
                        if (pTcpStruct.TcpOperationCommand == TcpOperationCommand.Message)
                        {
                            _Msg = Encoding.UTF8.GetString(pTcpStruct.Message);
                        }
                        else if (pTcpStruct.TcpOperationCommand == TcpOperationCommand.Closed)
                        {
                            _Msg = "服务端主动关闭连接";
                            _TcpClient?.Close();
                        }
                        else if (pTcpStruct.TcpOperationCommand == TcpOperationCommand.Error)
                        {
                            _Msg = Encoding.UTF8.GetString(pTcpStruct.Message);
                            _TcpClient?.Close();
                        }
                        else
                        {
                            _Msg = "未知错误";
                        }
                        pTcpStruct.ReadStatus = false;
                    }
                }
                else
                {
                    _Msg = "解析数据包出错，没有按照规定的协议进行打包";
                }
            }
            return pTcpStruct;
        }
        #endregion
        #region 读取、发送数据功能
        //private void ServerWrite(string pCommand, string pMsg)
        //{
        //    List<byte> fSendList = new List<byte>();
        //    byte[] fMsgBytes = Encoding.UTF8.GetBytes(pMsg);
        //    fSendList.AddRange(Encoding.UTF8.GetBytes(pCommand));
        //    fSendList.Add(TcpOperationCommand.ReadDataFenGe);
        //    fSendList.AddRange(Encoding.UTF8.GetBytes(fMsgBytes.Length.ToString()));
        //    fSendList.Add(TcpOperationCommand.ReadDataFenGe);
        //    fSendList.AddRange(fMsgBytes);
        //    ServerWriteBase(fSendList.ToArray());
        //}
        //private void ServerWrite(string pCommand, byte[] pMsgByte)
        //{
        //    List<byte> fSendList = new List<byte>();
        //    fSendList.AddRange(Encoding.UTF8.GetBytes(pCommand));
        //    fSendList.Add(TcpOperationCommand.ReadDataFenGe);
        //    fSendList.AddRange(Encoding.UTF8.GetBytes(pMsgByte.Length.ToString()));
        //    fSendList.Add(TcpOperationCommand.ReadDataFenGe);
        //    fSendList.AddRange(pMsgByte);
        //    ServerWriteBase(fSendList.ToArray());
        //}
        //private void ServerWriteBase(byte[] pBytes)
        //{
        //    //循环发送主数据包
        //    for (int i = 0; i < pBytes.Length; i += TcpOperationCommand.BytesMaxLenght)
        //    {
        //        byte[] fbytes = pBytes.Skip(i).Take(TcpOperationCommand.BytesMaxLenght).ToArray();
        //        _Stream.Write(fbytes, 0, fbytes.Length);
        //    }
        //}
        private void ServerSend(string pCommand, string pMsg)
        {
            List<byte> fSendList = new List<byte>();
            byte[] fMsgBytes = Encoding.UTF8.GetBytes(pMsg);
            fSendList.AddRange(Encoding.UTF8.GetBytes(pCommand));
            fSendList.Add(TcpOperationCommand.ReadDataFenGe);
            fSendList.AddRange(fMsgBytes);
            byte[] fFullByte = fSendList.ToArray();
            //计算数据包长度
            byte[] fBytelenght = BitConverter.GetBytes(fSendList.ToArray().Length);
            _Stream.Write(fBytelenght, 0, fBytelenght.Length);
            _Stream.Write(fFullByte, 0, fFullByte.Length);
        }
        private void ServerSend(string pCommand, byte[] pMsgByte)
        {
            List<byte> fSendList = new List<byte>();
            fSendList.AddRange(Encoding.UTF8.GetBytes(pCommand));
            fSendList.Add(TcpOperationCommand.ReadDataFenGe);
            fSendList.AddRange(pMsgByte);
            byte[] fFullByte = fSendList.ToArray();
            //计算数据包长度
            byte[] fBytelenght = BitConverter.GetBytes(fSendList.ToArray().Length);
            _Stream.Write(fBytelenght, 0, fBytelenght.Length);
            _Stream.Write(fFullByte, 0, fFullByte.Length);
        }
        /// <summary>
        /// 接收客户端数据
        /// </summary>
        /// <param name="pDataLen">数据长度</param>
        /// <param name="pStream"></param>
        /// <returns></returns>
        //private TcpReadStruct ServerRead()
        //{
        //    //回馈数据集
        //    TcpReadStruct fReturnRead = new TcpReadStruct();
        //    fReturnRead.ReadStatus = false;
        //    fReturnRead.Lenght = 0;
        //    // 分包数据集
        //    List<byte> packetBuffer = new List<byte>();
        //    //已经接收的数据包长度
        //    int fReadDataLenght = 0;
        //    //单次接收的数据包长度
        //    int fbytesCount;
        //    try
        //    {
        //        do
        //        {
        //            byte[] TcpDataBytes = new byte[TcpOperationCommand.BytesMaxLenght];
        //            fbytesCount = _Stream.Read(TcpDataBytes, 0, TcpDataBytes.Length);
        //            if (fReadDataLenght == 0)
        //            {
        //               List<byte[]> fBytesList = OtherFun.BytesSplit(TcpDataBytes, TcpOperationCommand.ReadDataFenGe);
        //                if (fBytesList.Count >= 3)
        //                {
        //                    for (int i = 0; i < fBytesList.Count; i++)
        //                    {
        //                        if (i == 0)
        //                        {
        //                            fReturnRead.TcpOperationCommand = Encoding.UTF8.GetString(fBytesList[i]);
        //                            fReadDataLenght -= fBytesList[i].Length;
        //                        }
        //                        else if (i == 1)
        //                        {
        //                            fReturnRead.Lenght = Convert.ToInt32(Encoding.UTF8.GetString(fBytesList[i]));
        //                            fReadDataLenght -= fBytesList[i].Length;
        //                        }
        //                        else
        //                        {
        //                            packetBuffer.AddRange(fBytesList[i]);
        //                        }
        //                    }
        //                }
        //            }
        //            else
        //            {
        //                packetBuffer.AddRange(TcpDataBytes);
        //            }
        //            fReadDataLenght += fbytesCount;
        //        }
        //        while (fReadDataLenght < fReturnRead.Lenght);
        //        fReturnRead.Message =OtherFun.BytesTrimEnd(packetBuffer.ToArray());
        //        fReturnRead.ReadStatus = true;
        //    }
        //    catch (Exception ex)
        //    {
        //        fReturnRead.ReadStatus = false;
        //        fReturnRead.ErrorMsg = ex.ToString();
        //    }
        //    return fReturnRead;
        //}
        private TcpReadStruct ServerRead()
        {
            //回馈数据集
            TcpReadStruct fReturnRead = new TcpReadStruct();
            fReturnRead.ReadStatus = false;
            fReturnRead.Lenght = 0;

            byte[] lengthBuffer = new byte[4];
            int bytesRead = 0;
            int length = 0;
            while (bytesRead < 4)
            {
                int read = _Stream.Read(lengthBuffer, bytesRead, 4 - bytesRead);
                if (read == 0)
                {
                    _Msg = "服务器回馈数据长度异常";
                    return fReturnRead;
                }
                bytesRead += read;
            }
            length = BitConverter.ToInt32(lengthBuffer, 0);

            byte[] dataBuffer = new byte[length];
            bytesRead = 0;
            while (bytesRead < length)
            {
                int read = _Stream.Read(dataBuffer, bytesRead, length - bytesRead);
                if (read == 0)
                {
                    _Msg = "没有数据包";
                   // LogWrite(pClientName, "没有数据包");
                    return fReturnRead;
                }
                bytesRead += read;
            }
            //处理数据
            List<byte[]> fBytesList = OtherFun.BytesSplitFor1(dataBuffer, TcpOperationCommand.ReadDataFenGe);
            if (fBytesList.Count == 2)
            {
                fReturnRead.ReadStatus = true;
                fReturnRead.TcpOperationCommand = Encoding.UTF8.GetString(fBytesList[0]);
                fReturnRead.Message = fBytesList[1];
            }
            return fReturnRead;
        }
        #endregion
    }
}